﻿// ***********************************************************************
// Assembly         : STX.Repository
// Author           : seven.x
// Created          : 12-29-2013
//
// Last Modified By : seven.x
// Last Modified On : 01-03-2014
// ***********************************************************************
// <copyright file="TransactionContext.cs" company="驰创数码">
//     Copyright (c) 驰创数码. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using STX.Domain;
using System.Configuration;

namespace STX.Repository
{
    /// <summary>
    /// Class EfTransactionContext.
    /// </summary>
    public class EfTransactionContext : ITransactionContext
    {
        /// <summary>
        /// The _repository cache
        /// </summary>
        private Dictionary<Type, object> _repositoryCache = new Dictionary<Type, object>();

        /// <summary>
        /// The _master context
        /// </summary>
        private DataBaseContext _masterContext;
        /// <summary>
        /// The _slaver database contexts
        /// </summary>
        private List<DataBaseContext> _slaverDbContexts;

        /// <summary>
        /// Initializes a new instance of the <see cref="EfTransactionContext"/> class.
        /// </summary>
        /// <exception cref="System.Exception">数据库配置有问题，请检查 stx.config 中connectionStrings节</exception>
        public EfTransactionContext()
        {
            _slaverDbContexts = new List<DataBaseContext>();
            var connections = ConfigurationManager.ConnectionStrings;
            foreach (ConnectionStringSettings connection in connections)
            {
                var name = connection.Name.ToLower();
                if (name == "default" || name == "master")
                {
                    _masterContext = new DataBaseContext(connection.Name);
                }
                else if (name.Contains("slave"))
                {
                    _slaverDbContexts.Add(new DataBaseContext(connection.Name));
                }
            }
            if (_masterContext == null)
            {
                throw new Exception("数据库配置有问题，请检查 stx.config 中connectionStrings节");
            }
        }

        #region IRepositoryTransactionContext Members

        /// <summary>
        /// Gets the repository.
        /// </summary>
        /// <typeparam name="TEntity">The type of the attribute entity.</typeparam>
        /// <returns>STX.Repository.IRepository{TEntity}.</returns>
        public IRepository<TEntity> GetRepository<TEntity>()
            where TEntity : BaseEntity

        {
            if (_repositoryCache.ContainsKey(typeof (TEntity)))
            {
                return (IRepository<TEntity>) _repositoryCache[typeof (TEntity)];
            }
            IRepository<TEntity> repository = new RepositoryProduction<TEntity>(_masterContext,_slaverDbContexts);
            this._repositoryCache.Add(typeof (TEntity), repository);
            return repository;
        }

        /// <summary>
        /// Begins the transaction.
        /// </summary>
        public void BeginTransaction()
        {
            // We do not need to begin a transaction here because the object context,
            // which would handle the transaction, was created and injected into the
            // constructor by Castle Windsor framework.
        }

        /// <summary>
        /// Commits this instance.
        /// </summary>
        public void Commit()
        {
            AffectedRows = _masterContext.SaveChanges();
        }

        /// <summary>
        /// Rollbacks this instance.
        /// </summary>
        public void Rollback()
        {
            // We also do not need to perform the rollback operation because
            // entity framework will handle this for us, just when the execution
            // point is stepping out of the using scope.
        }

        /// <summary>
        /// Gets the affected rows.
        /// </summary>
        /// <value>The affected rows.</value>
        public int AffectedRows
        {
            get; private set;
        }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务。
        /// </summary>
        public void Dispose()
        {
            _masterContext.Dispose();
            foreach (var slaverDbContext in _slaverDbContexts)
            {
                slaverDbContext.Dispose();
            }
            _repositoryCache.Clear();
        }
        #endregion
  
    }
}
